<?php
declare(strict_types=1);

namespace Reven\HyperfRedisBasics\occ;

use Reven\HyperfRedisBasics\exception\ConcurrencyException;
use Reven\HyperfRedisBasics\RedisTrait;

/**
 * redis 版本号控制并发
 * Class Version
 * @package HyperfRedis\concurrency
 */
class Version
{
    protected string $redisKey;

    protected int $ttl;

    protected int $version;

    use RedisTrait;

    /**
     * Lock constructor.
     * @param string $redisKey
     * @param int $ttl 有效期单位毫秒
     * @throws ConcurrencyException
     */
    public function __construct(string $redisKey,int $ttl=8640000)
    {
        $this->ttl=$ttl;
        $this->redisKey=$redisKey;
        $this->init();
        $this->initVersion();
    }


    /**
     * @throws ConcurrencyException
     */
    private function initVersion(){
        if (!$this->redis->exists($this->redisKey))
        {
            $re=$this->redis->setnx($this->redisKey,0);
            if (!$re){
                throw new ConcurrencyException("Too many users. Try again later");
            }
            $this->redis->pExpire($this->redisKey,$this->ttl);
        }

        $this->version=(int)$this->redis->get($this->redisKey);
    }


    /**
     * 提交
     * @throws ConcurrencyException
     */
    public function commit(){
        $setGetVersion=(int)$this->redis->getSet($this->redisKey,$this->version+1);
        if ($this->version!==$setGetVersion){
            throw new ConcurrencyException("commit Too many users. Try again later");
        }
        $this->redis->pExpire($this->redisKey,$this->ttl);
    }
}